<?php

namespace app\command;

use app\admin\model\Config;
use app\model\AdminAgent;
use app\model\AgentDistribution;
use app\model\DistributionSetting;
use app\model\Order;
use app\model\OrderInfo;
use app\model\OrderTeamCommissionLogModel;
use app\model\User;
use app\model\UserBalanceLog;
use app\service\AggregationService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use think\Db;
use think\facade\Log;

class AggregationOrderCommand extends Command
{
	protected function configure()
	{
		$startTime = date("Y-m-d H:i:s", strtotime('-1 hours'));
		$endTime   = date("Y-m-d H:i:s");
		$this->setName('aggregation-order')
			->addArgument('startTime', Argument::OPTIONAL, '开始时间', $startTime)
			->addArgument('endTime', Argument::OPTIONAL, '结束时间', $endTime)
			->setDescription('获取佣金单列表');
	}

	/**
	 * @throws Exception
	 * @throws GuzzleException
	 * 5分钟执行一次，获取5分钟内的订单
	 */
	protected function execute(Input $input, Output $output)
	{
		$datetime = date('Y-m-d H:i:s');
		echo "{$datetime} do aggregation-order...\n";

		$startTime = $input->getArgument('startTime');
		$endTime   = $input->getArgument('endTime');

		Log::init([
			'type'        => 'file',
			'apart_level' => ['error'],
			'level'       => ['error'],
			'path'        => app()->getRootPath() . "runtime/log/aggregation/",
			'max_files'   => 15,
		]);

		try {
			$isWhile = true;
			while ($isWhile) {
				$instance = AggregationService::getInstance();
				$instance->initStartEndTime($startTime, $endTime);

				$result = $instance->getOrderList();

				$userSecretList = array_column($result['data'], 'sid');
				$orderIds       = array_column($result['data'], 'order_sn');

				// 查询用户列表
				$userList    = User::field('id,parent_user_id,agent_id,user_secret,level,rank,order_count')->whereIn('user_secret', $userSecretList)->select()->toArray();
				$userListMap = array_column($userList, null, 'user_secret');

				// 创建订单
				$this->handleCreateOrder($result, $userListMap, $orderIds);
////				// 更新订单
//				$this->handleUpdateOrder($result, $userListMap, $orderIds);

				$currentTotal = (($result['current_page'] - 1) * $result['per_page']) + count($result['data']);
				if ($currentTotal >= $result['total']) {
					$isWhile = false;
				}
			}

		} catch (Exception $e) {
			Log::error([
				'message' => $e->getMessage(),
				'line'    => $e->getLine(),
				'file'    => $e->getFile(),
				'trace'   => $e->getTraceAsString(),
			]);
		}
	}

	/**
	 * 创建订单
	 *
	 * @param array $result
	 * @param array $userListMap
	 * @param array $orderIds
	 * @return void
	 */
	private function handleCreateOrder(array $result, array $userListMap, array $orderIds): void
	{

		// 查询订单是否存在
		$orderList    = Order::field('id,user_id,order_id,status,commission_status,actual_commission,total')->whereIn('order_id', $orderIds)->select()->toArray();
		$orderListMap = array_column($orderList, null, 'order_id');


		foreach ($result['data'] as $item) {
			try {
				$orderId    = $item['order_sn'];
				$orderInfo  = $orderListMap[$orderId] ?? [];
				$userSecret = $item['sid'];
				$userInfo   = $userListMap[$userSecret] ?? [];

				// 如果订单存在则跳过
				if (!empty($orderInfo)) {
					continue;
				}
				$createOrderData = $this->_handleCreateOrderData($item, $userInfo);

				Db::transaction(function () use ($createOrderData) {
					// 创建订单
					$res = Order::create($createOrderData['createOrder']);
					// 创建订单详情
					$createOrderData['createOrderInfo']['order_id'] = $res->id;
					OrderInfo::create($createOrderData['createOrderInfo']);
					// 创建分佣记录
					if ($createOrderData['commissionLog']) {
						UserBalanceLog::create($createOrderData['commissionLog']);
					}
					// 创建邀请人分佣记录
					if ($createOrderData['pUserCommissionLog']) {
						UserBalanceLog::create($createOrderData['pUserCommissionLog']);
					}
				});
			} catch (Exception $e) {
				Log::error([
					'message' => $e->getMessage(),
					'line'    => $e->getLine(),
					'file'    => $e->getFile(),
					'trace'   => $e->getTraceAsString(),
				]);
			}
		}
	}

	/**
	 * @param $item
	 * @param $userInfo
	 * @return array
	 */
	private function _handleCreateOrderData($item, $userInfo): array
	{
		//推客分享赚佣金
		$setting = [];
		if (!empty($userInfo)) {
			$setting = AgentDistribution::getLevelInfo(0, $userInfo['level'], 1);
		}
		$ratio      = isset($setting['ratio']) ? $setting['ratio'] / 100 : 0;            //推客分享赚佣金比例
		$type       = $setting['type'] ?? 0;                                              //分销类型，0：关闭，1：一级
		$ratioOne   = isset($setting['ratio_one']) ? $setting['ratio_one'] / 100 : 0; //一级分销比例
		$commission = round($item['jtk_share_fee'] * $ratio * 100);                 // 计算为分

		$oneCommission = 0;
		//如果开启分销，且用户有上级，则一级分销佣金 = 实际佣金 * 一级分销比例
		if ($type && $userInfo['parent_user_id'] > 0 && $ratioOne > 0) {
			$oneCommission = round($item['jtk_share_fee'] * $ratioOne * 100);
		}

		//利润 = 实际佣金 - 推客佣金
		$profit = ($item['jtk_share_fee'] * 100) - $commission;

		list($orderStatus, $commissionStatus) = $this->covertStatus($item['status']);

		// 整理创建订单数据
		$createOrder = [
			'brand_id'                 => $item['brand_id'],
			'user_id'                  => $userInfo['id'] ?? 0,
			'agent_id'                 => $userInfo['agent_id'] ?? 0,
			'goods_id'                 => 0, // 此类型订单，商城内无商品
			'product_id'               => '',
			'shop_appid'               => '',
			'order_id'                 => $item['order_sn'],
			'sku_id'                   => 0,
			'title'                    => $item['order_title'],
			'image'                    => $item['icon'],
			'total'                    => $item['pay_price'] * 100,
			'actual_commission'        => $item['jtk_share_fee'] * 100,
			'commission'               => $commission,
			'share_commission'         => 0, // TODO 没有分享逻辑，有了分享逻辑再加
			'subsidy_commission'       => 0, // 无补贴用尽逻辑
			'one_commission'           => $oneCommission,
			'agent_commission'         => 0, // 无合作商佣金逻辑
			'agent_subsidy_commission' => 0, // 无合作商推客补贴佣金逻辑
			'agent_shop_commission'    => 0, // 无合作商小店补贴佣金逻辑
			'agent_shop_agent'         => 0, // 无小店补贴佣金合作商ID
			'profit'                   => $profit,
			'is_free'                  => 0, // TODO 无0元购逻辑
			'status'                   => $orderStatus,
			'commission_status'        => $commissionStatus,
		];

		// 创建订单详情
		$createOrderInfo = [
			'shop_info'       => '{}', // 无此字段，设置为空json
			'product_info'    => '{}', // 无此字段，设置为空json
			'order_info'      => json_encode($item, JSON_UNESCAPED_UNICODE),
			'commission_info' => '{}', // 无此字段，设置为空json
			'buyer_info'      => '{}', // 无此字段，设置为空json
		];

		$commissionLog = [];
		$money         = round($commission / 100, 2);
		if ($userInfo && $money > 0) {
			$commissionLog = [
				'user_id'      => $userInfo['id'],
				'from_user_id' => $userInfo['id'],
				'type'         => UserBalanceLog::TYPE_NEED_RECEIVE,
				'scene'        => UserBalanceLog::SCENE_SHARE_ORDER,
				'money'        => $money,
				'order_money'  => $item['pay_price'],
				'order_id'     => $item['order_sn'],
			];
		}

		$pUserCommissionLog = [];
		if ($userInfo && $userInfo['parent_user_id'] > 0) {
			$pUser = User::field('id, parent_user_id, level, agent_id')->where('id', $userInfo['parent_user_id'])->find();
			if (!empty($pUser) && $pUser['level'] >= 2) {
				$config             = Config::where('name', '=', 'real_name')->value('value');
				$pUserCommissionLog = [
					'user_id'      => $pUser['id'],
					'from_user_id' => $userInfo['id'],
					'type'         => UserBalanceLog::TYPE_NEED_RECEIVE,
					'scene'        => UserBalanceLog::SCENE_CREATE_ORDER,
					'money'        => $config,
					'order_money'  => $item['pay_price'],
					'order_id'     => $item['order_sn'],
				];
			}
		}

		return [
			'createOrder'        => $createOrder,
			'createOrderInfo'    => $createOrderInfo,
			'commissionLog'      => $commissionLog,
			'pUserCommissionLog' => $pUserCommissionLog,
		];
	}

	/**
	 * 转换状态
	 *
	 * @param int $status
	 * @return array
	 */
	private function covertStatus(int $status): array
	{
		// 订单统一状态，0：未付款 1：已付款 2：待结算 3：已结算 4：无效订单
		$orderStatus      = Order::STATUS_WAIT;
		$commissionStatus = Order::COMMISSION_STATUS_WAIT;
		// 订单状态，10：待付款，12：待收礼，20：待发货，21：部分发货，30：待收货，100：完成，200：全部商品售后之后，订单取消，250：未付款用户主动取消或超时未付款订单自动取消
		// 佣金状态，20：未结算，100：已结算，200：取消结算
		if ($status == 1) {
			$orderStatus = Order::STATUS_DELIVERY_WAIT; // 已付款待发货
		} else if ($status == 2) {
			$orderStatus = Order::STATUS_RECEIVE_WAIT; // 待收货(待结算)
		} else if ($status == 3) {
			$orderStatus      = Order::STATUS_COMPLETE;                 // 已结算(已完成)
			$commissionStatus = Order::COMMISSION_STATUS_COMPLETE; // 已结算
		} else if ($status == 4) {
			$commissionStatus = Order::COMMISSION_STATUS_CANCEL; // 无效订单(取消结算)
			$orderStatus      = Order::STATUS_AUTO_CANCEL;            // 无效订单(自动取消)
		}

		return [$orderStatus, $commissionStatus];
	}

	/**
	 * 更新订单
	 *
	 * @param array $result
	 * @param array $userListMap
	 * @param array $orderIds
	 * @return void
	 */
	private function handleUpdateOrder(array $result, array $userListMap, array $orderIds): void
	{

		// 查询订单是否存在
		$orderList    = Order::field('id,user_id,agent_id,order_id,status,commission_status,actual_commission,total')->whereIn('order_id', $orderIds)->select()->toArray();
		$orderListMap = array_column($orderList, null, 'order_id');

		// 查询用户分佣记录
		$userBalanceList = UserBalanceLog::field('log_id,user_id,order_id,money,status')->whereIn('order_id', $orderIds)->select()->toArray();

		$userBalanceListMap = [];
		foreach ($userBalanceList as $item) {
			$userBalanceListMap[$item['order_id']][] = $item;
		}

		foreach ($result['data'] as $item) {
			try {
				$orderId         = $item['order_sn'];
				$orderInfo       = $orderListMap[$orderId] ?? [];
				$userSecret      = $item['sid'];
				$userInfo        = $userListMap[$userSecret] ?? [];
				$userBalanceList = [];
				if ($userInfo) {
					$userBalanceList = $userBalanceListMap[$orderId] ?? [];
				}

				// 如果订单不存在则跳过
				if (empty($orderInfo)) {
					continue;
				}

				// 如果有订单，则更新订单状态 && 发放佣金
				$this->_handleUpdateOrderData($item, $orderInfo, $userInfo, $userBalanceList);

			} catch (Exception $e) {
				Log::error([
					'message' => $e->getMessage(),
					'line'    => $e->getLine(),
					'file'    => $e->getFile(),
					'trace'   => $e->getTraceAsString(),
				]);
			}
		}

	}

	/**
	 * @param $item
	 * @param $orderInfo
	 * @param $userInfo
	 * @param $userBalanceList
	 * @return void
	 */
	private function _handleUpdateOrderData($item, $orderInfo, $userInfo, $userBalanceList): void
	{
		list($orderStatus, $commissionStatus) = $this->covertStatus($item['status']);
		// 查询订单状态是否相同
		if ($orderInfo['status'] == $orderStatus && $orderInfo['commission_status'] == $commissionStatus) {

			$isCompleted = true;
			foreach ($userBalanceList as $value) {
				if ($value['status'] != UserBalanceLog::STATUS_COMPLETED) {
					$isCompleted = false;
				}
			}

			if ($isCompleted === true) {
				return;
			}
		}

		// 订单状态更新信息
		$updateOrderData = [
			'status'            => $orderStatus,
			'commission_status' => $commissionStatus,
		];

		// 处理订单数据变更，处理分佣记录状态变更
		Db::transaction(function () use ($item, $orderInfo, $userInfo, $updateOrderData, $userBalanceList, $orderStatus, $commissionStatus) {
			// 更新订单状态
			Order::where('order_id', $item['order_sn'])->update($updateOrderData);
			// 状态已完成
			if ($orderStatus == 100 && $commissionStatus == 100) {
				$res = $this->updateUserBalance($orderInfo, $userInfo, $userBalanceList);
				if (!$res) {
					Log::error('更新用户余额失败：' . $orderInfo['order_id']);
					throw new Exception('更新用户余额失败：' . $orderInfo['order_id']);
				}
			}
			// 订单取消，则把分佣记录改为已取消状态
			if (in_array($orderStatus, [Order::STATUS_CANCEL, Order::STATUS_AUTO_CANCEL]) && $commissionStatus == Order::COMMISSION_STATUS_CANCEL) {
				UserBalanceLog::where('order_id', $item['order_sn'])->update([
					'status' => UserBalanceLog::STATUS_CANCEL,
				]);
			}
		});
	}

	/**
	 * @param array $orderInfo
	 * @param array $userInfo
	 * @param array $userBalanceList
	 * @return bool
	 */
	private function updateUserBalance(array $orderInfo, array $userInfo, array $userBalanceList): bool
	{

		// 用户不存在，则不发放佣金
		if (empty($userInfo)) {
			return true;
		}
		$userRes = User::where('id', $userInfo['id'])->update([
			'order_count' => $userInfo['order_count'] + 1,
		]);


		// 佣金奖励
		$userModel           = new User();
		$UserBalanceLogModel = new UserBalanceLog();

		$updateStatusLogIds = [];
		// 将分佣金额加到用户余额
		foreach ($userBalanceList as $value) {
			$updateStatusLogIds[] = $value['log_id']; // 提交事物之前，会将主键id放入 id 字段，无论主键id是否叫做id
			$userModel->setIncMoney($value['user_id'], $value['money'] * 100);
			$userModel->setIncTotal($value['user_id'], $value['money'] * 100);
		}

		// 给用户账户分佣后，将状态改为已结算
		$UserBalanceLogModel->whereIn('log_id', $updateStatusLogIds)->update([
			'status' => UserBalanceLog::STATUS_COMPLETED,
		]);

		// 团队奖励
		$team_ids      = explode('|', trim($userInfo['rank'], '|'));
		$team_ids      = array_reverse(array_slice(array_reverse($team_ids), 0, 9));
		$team_user_ids = $userModel->where('id', 'in', $team_ids)->where('level', '=', 3)->column('id');

		// 获取当前分佣队列开头的数据
		$firstOrderTeamCommissionId = OrderTeamCommissionLogModel::where('user_id', $orderInfo['user_id'])
			->where('level', 1)
			->order('id', 'desc')
			->value('id');
		// 获取当前分佣队列数据
		$orderTeamCommissionLogCount = OrderTeamCommissionLogModel::where('user_id', $orderInfo['user_id'])
			->where('id', '>=', $firstOrderTeamCommissionId)
			->count();
		$orderTeamCommissionLogCount = intval($orderTeamCommissionLogCount);
		$nextUserId                  = $team_ids[0];
		$level                       = 1;

		if ($orderTeamCommissionLogCount < count($team_ids)) {
			$nextUserId = $team_ids[$orderTeamCommissionLogCount];
			$level      = $orderTeamCommissionLogCount + 1;
		}
		if ($orderTeamCommissionLogCount == count($team_ids)) {
			$nextUserId = 0;
			$level      = $orderTeamCommissionLogCount + 1;
		}

		if (in_array($nextUserId, $team_user_ids)) {
			$setting     = DistributionSetting::getLevelInfo(3, 1);
			$team_reward = round($setting['team_ratio'] * $orderInfo['actual_commission'] / 10000, 2);

			if ($team_reward > 0) {
				// 将金额发放到用户余额 && 累计总收益金额
				$userModel->setIncMoney($nextUserId, $team_reward * 100);
				$userModel->setIncTotal($nextUserId, $team_reward * 100);

				// 创建分佣记录信息
				UserBalanceLog::create([
					'user_id'      => $nextUserId,
					'from_user_id' => $userInfo['id'],
					'type'         => UserBalanceLog::TYPE_NEED_RECEIVE,
					'scene'        => UserBalanceLog::SCENE_TEAM,
					'money'        => $team_reward,
					'order_money'  => round($orderInfo['total'] / 100, 2),
					'order_id'     => $orderInfo['order_id'],
					'status'       => UserBalanceLog::STATUS_COMPLETED,
				]);

				// 添加订单团队分佣记录表 给系统分佣的话，也需要记录
				OrderTeamCommissionLogModel::create([
					'level'                     => $level,
					'user_id'                   => $orderInfo['user_id'],
					'order_id'                  => $orderInfo['order_id'],
					'commission_user_id'        => $nextUserId,
					'actual_commission_user_id' => in_array($nextUserId, $team_user_ids) ? $nextUserId : 0,
					'created_at'                => date('Y-m-d H:i:s'),
					'updated_at'                => date('Y-m-d H:i:s'),
				]);
			}
		}

		$agent_res = $shop_agent_res = true;
		if ($orderInfo['agent_id'] > 0) {
			$agent = AdminAgent::field('id, total_money, money')->where('id', $orderInfo['agent_id'])->find();
			//如果小店补贴佣金跟推客所属的合作商不一样，则代理商佣金需要减去小店补贴佣金
			$shop_agent = null;
			if ($orderInfo['agent_id'] != $orderInfo['agent_shop_agent']) {
				$agent_commission = $orderInfo['agent_commission'] - $orderInfo['agent_shop_commission'];
				$shop_agent       = AdminAgent::field('id, total_money, money')->where('id', $orderInfo['agent_shop_agent'])->find();
			} else {
				$agent_commission = $orderInfo['agent_commission'];
			}

			$agent_res = AdminAgent::where('id', $agent['id'])->update([
				'total_money' => $agent['total_money'] + $agent_commission,
				'money'       => $agent['money'] + $agent_commission,
			]);
			if ($shop_agent) {
				$shop_agent_res = AdminAgent::where('id', $orderInfo['agent_shop_agent'])->update([
					'total_money' => $shop_agent['total_money'] + $orderInfo['agent_shop_commission'],
					'money'       => $shop_agent['money'] + $orderInfo['agent_shop_commission'],
				]);
			}
		}
		if ($userRes && $agent_res && $shop_agent_res) {
			return true;
		}
		return false;
	}
}